<template>
  <div
    class="paragraph-block"
    :class="{ open: showMenu, mobile: isMobile }"
    ref="rootEl"
    :id="anchorId || undefined"
  >
    <!-- 文字主体 -->
    <div class="original">{{ original }}</div>
    <div v-if="showTranslation && translation" class="translation">{{ translation }}</div>

    <!-- 三点触发按钮：hover 显示 / 打开时常显 -->
    <button
      type="button"
      class="trigger-btn"
      :aria-expanded="showMenu ? 'true' : 'false'"
      aria-haspopup="true"
      @click.stop="toggleMenu"
    >
      <span class="dot"/><span class="dot"/><span class="dot"/>
    </button>

    <!-- 弹出菜单 -->
    <transition name="fade-scale">
      <div
        v-if="showMenu"
        class="menu-panel"
        role="menu"
        @click.stop
      >
        <button class="menu-item" role="menuitem" @click="onTranslate" :disabled="translating">
          <span v-if="!translating">{{ translationLabel }}</span>
          <span v-else>载入…</span>
        </button>
  <button class="menu-item" role="menuitem" @click="onAiInterpret">{{ aiInterpretLabel }}</button>
        <button class="menu-item" role="menuitem" @click="onAiImage">{{ aiImageLabel }}</button>
      </div>
    </transition>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, computed, watch, nextTick } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { ElMessage } from 'element-plus'

const props = defineProps({
  original: { type: String, required: true },
  translation: { type: String, default: '' },
  forceActions: { type: Boolean, default: false }, // 未来移动端 tap 控制
  anchorId: { type: String, default: '' }, // 段落唯一锚点 id
  highlight: { type: Boolean, default: false }, // 初次定位高亮
  bookId: { type: [Number, String], default: null },
  bookTitle: { type: String, default: '' },
  chapterId: { type: [Number, String], default: null },
  sectionIndex: { type: Number, default: null },
  paragraphIndex: { type: Number, default: null }
})

// 预留未来远程翻译加载状态
const translating = ref(false)
const showTranslation = ref(true)
const showMenu = ref(false)
const isMobile = ref(false)

// 自适应短标签，避免窄屏溢出
const translationLabel = computed(() => isMobile.value ? (showTranslation.value ? '隐藏译文' : '译文') : (showTranslation.value ? '隐藏译文' : '显示译文'))
const aiInterpretLabel = computed(() => isMobile.value ? '解读' : 'AI 解读')
// 已启用：移除 soon 提示
const aiImageLabel = computed(() => isMobile.value ? '生图' : 'AI 生图')

function toggleMenu() {
  showMenu.value = !showMenu.value
}
function handleOutside(e) {
  if (!showMenu.value) return
  // 若点击发生在当前段落内部（包含菜单或按钮）则忽略
  const root = rootEl.value
  if (root && root.contains(e.target)) return
  showMenu.value = false
}
const rootEl = ref(null)

function updateIsMobile() { isMobile.value = window.innerWidth < 980 }

let highlightTimers = []
function clearHighlightTimers() {
  highlightTimers.forEach(t => clearTimeout(t))
  highlightTimers = []
}
function runHighlight() {
  const el = rootEl.value
  if (!el) return
  clearHighlightTimers()
  el.classList.remove('flash-highlight', 'flash-dim', 'soft-hold', 'soft-hold-fade')
  void el.offsetWidth
  el.classList.add('flash-highlight')
  highlightTimers.push(setTimeout(() => { el && el.classList.add('flash-dim') }, 80))
  highlightTimers.push(setTimeout(() => {
    if (!el) return
    el.classList.remove('flash-highlight', 'flash-dim')
  }, 2600))
}

onMounted(() => {
  updateIsMobile()
  window.addEventListener('resize', updateIsMobile, { passive: true })
  document.addEventListener('click', handleOutside, true)
  document.addEventListener('keydown', (ev) => {
    if (ev.key === 'Escape' && showMenu.value) showMenu.value = false
  })
  if (props.highlight) runHighlight()
})

watch(() => props.highlight, async (val) => {
  if (val) {
    await nextTick()
    runHighlight()
  }
})
onUnmounted(() => {
  window.removeEventListener('resize', updateIsMobile)
  document.removeEventListener('click', handleOutside, true)
  clearHighlightTimers()
})

function onTranslate(e) {
  // demo：切换译文显示；未来如果无 translation 可触发请求
  e.stopPropagation()
  if (!props.translation) {
    ElMessage.info('暂无内置译文，后续将支持在线翻译')
    return
  }
  showTranslation.value = !showTranslation.value
  // 关闭菜单以减少遮挡
  showMenu.value = false
}

const router = useRouter()
const route = useRoute()
function onAiImage(e) {
  e.stopPropagation()
  showMenu.value = false
  // 基础校验
  if (props.bookId == null || props.chapterId == null || props.sectionIndex == null || props.paragraphIndex == null) {
    ElMessage.warning('缺少上下文，无法跳转生图')
    return
  }
  // 构造 excerpt（截断）
  let excerpt = (props.original || '').trim().replace(/\s+/g, ' ')
  const MAX = 140
  let truncatedFlag = false
  if (excerpt.length > MAX) { excerpt = excerpt.slice(0, MAX) + '…'; truncatedFlag = true }
  // 精确返回路径：确保包含章节与段落 p 参数
  const returnPath = `/library/${props.bookId}?chapter=${props.chapterId}&p=${props.sectionIndex}-${props.paragraphIndex}`
  router.push({
    name: 'ImageGeneration',
    query: {
      book: props.bookId,
      bt: encodeURIComponent(props.bookTitle || ''),
      chapter: props.chapterId,
      sec: props.sectionIndex,
      para: props.paragraphIndex,
      excerpt: encodeURIComponent(excerpt),
      trunc: truncatedFlag ? 1 : 0,
      return: encodeURIComponent(returnPath)
    }
  })
}

function onAiInterpret(e) {
  e.stopPropagation()
  showMenu.value = false
  if (props.bookId == null || props.chapterId == null || props.sectionIndex == null || props.paragraphIndex == null) {
    ElMessage.warning('缺少上下文，无法跳转解读')
    return
  }
  let content = (props.original || '').trim()
  // 为解读保留更长文本，但做一个软上限避免 query 过长
  const MAX = 500
  let truncated = false
  if (content.length > MAX) { content = content.slice(0, MAX) + '…'; truncated = true }
  const returnPath = `/library/${props.bookId}?chapter=${props.chapterId}&p=${props.sectionIndex}-${props.paragraphIndex}`
  router.push({
    name: 'AIChat',
    query: {
      interpret: 1,
      book: props.bookId,
      bt: encodeURIComponent(props.bookTitle || ''),
      chapter: props.chapterId,
      sec: props.sectionIndex,
      para: props.paragraphIndex,
      text: encodeURIComponent(content),
      trunc: truncated ? 1 : 0,
      return: encodeURIComponent(returnPath)
    }
  })
}
</script>

<style scoped>
.paragraph-block { position:relative; margin:0 0 26px; line-height:1.85; font-size:15px; }
.paragraph-block:last-child { margin-bottom:0; }
.original { white-space:pre-wrap; font-family:'serif'; font-weight:500; color:#222; }
.translation { margin-top:8px; background:#f5f7fa; padding:10px 14px; border-left:4px solid #c3d0dc; border-radius:6px; font-size:13px; color:#4b5d66; line-height:1.65; }

/* 触发按钮（仅 hover 或展开时显示，不占文字宽度） */
.trigger-btn { position:absolute; top:4px; right:-6px; width:34px; height:30px; display:flex; align-items:center; justify-content:center; gap:3px; background:rgba(255,255,255,.55); backdrop-filter:blur(8px); border:1px solid rgba(185,198,209,.65); border-radius:14px; cursor:pointer; padding:0; opacity:0; transform:translateY(-4px); transition:opacity .18s ease, transform .18s ease, background .25s; box-shadow:0 2px 8px -2px rgba(0,0,0,.18); }
.trigger-btn .dot { width:4px; height:4px; background:#4b5d6a; border-radius:50%; display:block; }
.paragraph-block:hover > .trigger-btn, .paragraph-block.open > .trigger-btn { opacity:1; transform:translateY(0); }
.trigger-btn:hover { background:rgba(255,255,255,.9); }
.trigger-btn:active { transform:translateY(1px); }

/* 菜单面板 */
.menu-panel { position:absolute; top:-4px; right:36px; display:flex; flex-direction:column; gap:4px; min-width:140px; background:linear-gradient(155deg,rgba(255,255,255,.97),rgba(244,248,252,.96)); backdrop-filter:blur(10px) saturate(140%); border:1px solid #d0dae3; border-radius:14px; padding:10px 10px 8px; box-shadow:0 8px 28px -6px rgba(20,40,60,.25), 0 2px 6px -2px rgba(20,40,60,.18); z-index:5; }
.menu-item { appearance:none; border:0; background:transparent; text-align:left; font-size:13px; padding:8px 10px; border-radius:8px; color:#364a59; letter-spacing:.3px; cursor:pointer; font-weight:500; transition:background .16s ease,color .16s ease; }
.menu-item:hover:not(:disabled) { background:#2563eb15; color:#1d4ed8; }
.menu-item:active:not(:disabled) { background:#1d4ed82a; }
.menu-item:disabled { opacity:.45; cursor:default; }

/* 动画 */
.fade-scale-enter-active, .fade-scale-leave-active { transition: opacity .18s ease, transform .18s ease; transform-origin: top right; }
.fade-scale-enter-from, .fade-scale-leave-to { opacity:0; transform:scale(.92) translateY(-4px); }

@media (max-width: 980px) {
  .paragraph-block.mobile { padding-bottom:40px; }
  .trigger-btn { display:flex; opacity:1 !important; transform:none !important; top:auto; bottom:6px; right:10px; width:30px; height:30px; background:rgba(255,255,255,.78); border-radius:12px; box-shadow:0 2px 8px -2px rgba(0,0,0,.2); }
  .menu-panel { position:absolute; left:0; right:0; top:auto; bottom:4px; transform:none !important; min-width:0; flex-direction:row; justify-content:space-between; gap:6px; padding:6px 8px; border-radius:26px; backdrop-filter:blur(14px) saturate(160%); box-shadow:0 6px 18px -6px rgba(20,40,60,.28), inset 0 0 0 1px rgba(200,210,220,.35); }
  .menu-item { flex:1 1 0; min-width:0; white-space:nowrap; padding:6px 6px; font-size:12px; text-align:center; }
  .fade-scale-enter-from, .fade-scale-leave-to { transform:scale(.92); }
}

/* 定位高亮动画（暖色系：柔和琥珀/橙黄，不突兀） */
.paragraph-block.flash-highlight { position:relative; box-shadow:0 0 0 0 rgba(255,165,0,0.55), 0 0 0 4px rgba(255,196,54,0.40); border-radius:10px; animation: pulseBorderWarm 2s ease forwards; }
.paragraph-block.flash-highlight.flash-dim { box-shadow:0 0 0 0 rgba(255,165,0,0), 0 0 0 0 rgba(255,196,54,0); }
@keyframes pulseBorderWarm {
  0% { box-shadow:0 0 0 0 rgba(255,170,40,0), 0 0 0 0 rgba(255,200,60,0); background:rgba(255,255,240,0); }
  10% { box-shadow:0 0 0 0 rgba(255,170,40,0.60), 0 0 0 4px rgba(255,205,70,0.42); background:rgba(255,248,225,0.85); }
  55% { box-shadow:0 0 0 0 rgba(255,170,40,0.35), 0 0 0 3px rgba(255,200,65,0.30); background:rgba(255,249,230,0.45); }
  100% { box-shadow:0 0 0 0 rgba(255,170,40,0), 0 0 0 0 rgba(255,200,65,0); background:transparent; }
}
</style>